/**
 * 产品+组合 业务组件 树形结构
 * by zhangxinyue
 * create 2021-07-29
 */
import React from 'react';
import { connect } from 'dva';
import PropTypes from 'prop-types';
import { TreeSelect, Tooltip } from 'antd';
import moreMaxDataNeedModifys from './config';

let parentGetByValue = []; //存放搜索的后获取的相应的父元素的值
let parentNode = {}; //存放搜索的第一次进入拿到的父级数据

let parentGetByKeys = []; //存在初始值initalValue 存放通过key查找 父级元素存放数组
let parentNodeByKeys = {}; //存放第一次进入拿到的父级的数据

let valueData = null;

const { moreMaxDataNeedModify } = moreMaxDataNeedModifys;
class ProductGroupTreeC extends React.PureComponent {
  // props默认值
  static defaultProps = {
    placeholder: '请选择组合',
    onChange: () => {},
    onRef: () => {}, // 本组件的引用
    width: '100%',
    maxTagCount: 0,
    productId: undefined, // 默认无产品ID，获取所有产品下的组合
    ralation: false, // 默认单独展示，无关联关系
    rules: undefined, // 默认无校验规则
    multiple: true, // 默认支持多选
    allowClear: true, // 默认可删除
    authority: 'read', // 默认是读权限
    disabled: false, // 默认不禁用
    treeCheckable: false, // 默认不显示
    maatApi: false, // 默认什么环境下就用什么该环境的组合
    toolTipPlace: undefined, // tooltip显示位置(默认多选时展示在右边，单选时展示在上面)
    maxMountDataShow: moreMaxDataNeedModifys, //优化--若返回的数据大于100个，则进行优化，数量可控
  };

  constructor(props) {
    super(props);
    this.state = {
      groupDS: undefined, // 与产品有关联关系的数据源
      dataSource: undefined,
      treeExpandedKeys: [], // 记录树展开的节点（解决数据刷新时，树节点未默认展开问题）
      tooltipInfo: '', // 提示信息
      tooltips: null, //存放tooltip的值
      searchInputValue: null, //搜索框的值
      countBlur: 0,
      isClearAll: false, //是否删除了所有项目
      displayType: 2, //1、展示所有数据前300 2、展示选中项及其父级 3、展示搜索的前300
    };
  }

  componentDidMount() {
    // 父组件对本组件的引用
    this.props.onRef(this);
    if (this.props.productCode) {
      //如果是通过产品code查询组合列表，展示单个组合，负债端维护页面，请求对应接口得到productAGroupM.productGroup
      if (this.props.productAGroup2M.productGroupFuZhai && this.props.productAGroup2M.productGroupFuZhai.length > moreMaxDataNeedModify) {
        let keys = [];
        this.findParentKey(this.props.productAGroup2M.productGroupFuZhai, keys);
        this.setState({
          treeExpandedKeys: keys,
        });
      }
      return;
    }
    // 获取组合的全量数据(不管是否联动，都获取全量数据，方便onChange和tooltip获取信息)
    this.getProductGroup(undefined, this.props.authority, () => {
      if (!this.props.ralation && this.props.productAGroup2M.productGroup) {
        if (this.props.productAGroup2M.productGroup.length > moreMaxDataNeedModify) {
          let keys = [];
          this.findParentKey(this.props.productAGroup2M.productGroup, keys);
          this.setState({
            treeExpandedKeys: keys,
          });
        }
      }
      // 若有同步的初始化数据，则设置tooltip
      if (this.props.initialValue) {
        this.setTooltip(this.props.initialValue, this.props);
      }
    });
    // 联动时，有产品ID时，调用接口，获取产品下的组合
    if (this.props.ralation && this.props.productId) {
      // 有同步初始化值，则设置对应的tooltip
      if (this.props.initialValue) {
        this.initSeletData(this.props.productId, this.props.authority, true, this.props.initialValue);
      } else {
        this.initSeletData(this.props.productId, this.props.authority);
      }
    }
    // 联动同步无初始化添加提示
    if (this.props.ralation && !this.props.productId) {
      this.setState({
        groupDS: [{ value: 'blank', title: '请先选择产品', disabled: true }],
      });
    }
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    // 处理当重置时，清空tooltip
    let value = nextProps.form.getFieldValue(nextProps.dataIndex);

    this.setTooltip(value);
    if (!value) {
      this.setState({
        displayType: 1,
      });
    }
    const initValue = this.props.initialValue ? JSON.stringify(this.props.initialValue) : '';
    const initValueN = nextProps.initialValue ? JSON.stringify(nextProps.initialValue) : '';
    // 产品与组合联动
    if (this.props.ralation) {
      //判断产品是否渲染完成
      if (nextProps.dataIndex0 != undefined) {
        let value0 = nextProps.form.getFieldValue(nextProps.dataIndex0);
        if (value0 == undefined) {
          //处理当重置时，清空下拉数据
          this.props.resetChange(undefined);
        }
      }
      if (this.props.productId != nextProps.productId) {
        // 清空tooltip
        this.setState({
          tooltipInfo: '',
        });
        // productId==undefined，证明未选中任何产品，组合下拉内容置空
        if (nextProps.productId === undefined) {
          this.setState({
            groupDS: [{ value: 'blank', title: '请先选择产品', disabled: true }],
          });
        } else {
          // 若外部传了产品ID，则先把老的数据清除，再调用接口，根据产品ID，获取其下组合数据
          this.setState({
            groupDS: undefined,
          });
          // 若有初始化值，则设置tooltip
          if (initValue != initValueN) {
            this.initSeletData(nextProps.productId, nextProps.authority, true, nextProps.initialValue);
          } else {
            this.initSeletData(nextProps.productId, nextProps.authority);
          }
        }
      }
    } else {
      // 单组合，不与产品联动
      let ds = undefined;
      let dsN = undefined;
      if (this.props.productCode) {
        //负债端维护
        ds = this.props.productAGroup2M.productGroupFuZhai ? JSON.stringify(this.props.productAGroup2M.productGroupFuZhai) : '';
        dsN = nextProps.productAGroup2M.productGroupFuZhai ? JSON.stringify(nextProps.productAGroup2M.productGroupFuZhai) : '';
        if (this.props.productAGroup2M.productGroupFuZhai) {
          let keys = [];
          this.findParentKey(this.props.productAGroup2M.productGroupFuZhai, keys);
          this.setState({
            treeExpandedKeys: keys,
          });
        }
      } else {
        ds = this.props.productAGroup2M.productGroup ? JSON.stringify(this.props.productAGroup2M.productGroup) : '';
        dsN = nextProps.productAGroup2M.productGroup ? JSON.stringify(nextProps.productAGroup2M.productGroup) : '';
        if (this.props.productAGroup2M.productGroup && !this.props.investmentType) {
          let keys = [];
          this.findParentKey(this.props.productAGroup2M.productGroup, keys);
          this.setState({
            treeExpandedKeys: keys,
          });
        }
      }
      // 初始化值或全量数据变更时，设置tooltip
      if (initValue != initValueN || (ds != dsN && this.props.investmentType)) {
        this.setTooltip(nextProps.initialValue, nextProps);
      }
    }
  }

  // 非初始化状态下更改下拉选项(供父组件调用)
  setSelect = (value) => {
    const valueF = {};
    valueF[this.props.dataIndex] = value;
    this.props.form.setFieldsValue(valueF);

    this.setTooltip(value);
  };

  // 获取onchange应该对外抛出的内容（供父组件调用）
  setOnChangeInfo = (e) => {
    let args = { key: e, info: undefined };
    let ds = !this.props.investmentType
      ? this.props.productCode
        ? this.props.productAGroup2M.productGroupFuZhai
        : this.props.productAGroup2M.productGroup
      : this.state.dataSource;
    // 多选
    if (this.props.multiple) {
      let info = [];
      e.forEach((element) => {
        let nodeInfo = [];
        this.findNode(ds, element, nodeInfo);
        info.push(nodeInfo[0]);
      });
      args.info = info;
    } else {
      // 单选
      let nodeInfo = [];
      this.findNode(ds, e, nodeInfo);
      args.info = nodeInfo[0];
    }
    return args;
  };

  // 遍历树形结构，找出所有非叶子节点
  findParentKey = (data, keys) => {
    if (data && data.length > 0) {
      data.forEach((item) => {
        if (item && item.children && item.children.length > 0) {
          keys.push(item.key);
          this.findParentKey(item.children, keys);
        }
      });
    }
  };

  // 初始化下拉数据
  // productId-产品ID
  // authority-权限
  // setTooltip- 是否需要设置tooltip
  // value-若需要设置tooltip，那么对应的值是什么
  initSeletData = (productId, authority, setTooltip = false, value = undefined) => {
    //value是组合的默认值，如果没有默认值就是undefined  如果有默认值
    //args是获取的数据
    // 调用接口，获取产品下的组合数据
    this.getProductGroup(productId, authority, (args) => {
      this.setState({
        groupDS: args,
      });
      // 找出所有父节点，并展开
      let keys = [];
      this.findParentKey(args, keys);
      this.setState({
        treeExpandedKeys: keys,
      });
      // 设置tooltip
      if (setTooltip) {
        this.setTooltip(value);
      }
    });
  };

  // 根据节点value,找到节点
  findNode = (data, key, node) => {
    if (data && data.length > 0) {
      data.forEach((item) => {
        if (item && item.value == key) {
          node.push(item);
          return;
        } else if (item && item.children && item.children.length > 0) {
          this.findNode(item.children, key, node);
        }
      });
    }
  };

  // 设置tooltip
  setTooltip = (e, propT = this.props) => {
    let ds = propT.investmentType ? this.state.dataSource : propT.productCode ? propT.productAGroup2M.productGroupFuZhai : propT.productAGroup2M.productGroup;
    if (ds == undefined) return;

    let { multiple } = propT;
    let tooltipInfo = '';
    if (e != undefined && e != null) {
      if (Array.isArray(e) && multiple) {
        // 多选
        e.forEach((element, index) => {
          let nodeInfo = [];
          this.findNode(ds, element, nodeInfo);

          if (nodeInfo.length > 0) {
            tooltipInfo += nodeInfo[0].title;
          }
          // 最后一个元素之后不用换行
          if (index != e.length - 1) {
            tooltipInfo += '\r\n';
          }
        });
      } else {
        // 单选
        let nodeInfo = [];
        this.findNode(ds, e, nodeInfo);
        if (nodeInfo.length > 0) {
          tooltipInfo += nodeInfo[0].title;
        }
      }
    }
    this.setState({
      tooltipInfo: tooltipInfo == '' ? '' : <div style={{ whiteSpace: 'pre' }}>{tooltipInfo}</div>,
      tooltips: multiple ? e : [e],
    });
  };

  // 调用接口，获取产品+组合树形结构
  getProductGroup = (productId, authority, callback) => {
    let that = this;
    const { investmentType } = this.props;
    // 当设置了产品ID时，获取产品下的组合
    if (productId) {
      this.props.dispatch({
        type: 'productAGroup2M/getProductGroup',
        payload: {
          rootId: productId,
          authority: authority,
          maatApi: this.props.maatApi,
          inveType: this.props.inveType,
          tradeModel: this.props.tradeModel,
        },
        callback: callback,
      });
    } else {
      // 当未设置产品ID时，获取全量信息
      let params = {
        authority: authority,
        maatApi: this.props.maatApi,
        inveType: this.props.inveType,
        tradeModel: this.props.tradeModel,
      };
      if (investmentType) {
        params.investmentType = investmentType;
        that.props.dispatch({
          type: 'productAGroup2M/getProductGroup',
          payload: {
            ...params,
          },
          callback: (res) => {
            let keys = [];
            that.findParentKey(res, keys);
            that.setState({
              dataSource: res,
              treeExpandedKeys: keys,
            });

            // 若有同步的初始化数据，则设置tooltip
            if (that.props.initialValue) {
              that.setTooltip(that.props.initialValue, that.props);
            }
          },
        });
        return;
      }
      this.props.dispatch({
        type: 'productAGroup2M/getProductGroup',
        payload: {
          ...params,
        },
        callback: callback,
      });
    }
  };

  // 树节点展开事件，解决数据刷新时，树节点未默认展开问题
  onTreeExpand = (expandedKeys) => {
    this.setState({
      treeExpandedKeys: expandedKeys,
    });
  };

  // 选中树节点变更事件
  onChange = (e) => {
    const { value, multiple } = this.props;
    if (!e || e?.length == 0) {
      this.setState({
        searchInputValue: '',
        displayType: 1,
      });
    } else if ((multiple && value?.length > e.length) || !multiple) {
      this.setState({
        displayType: 2,
      });
    }
    //此处需要注意当如果是有默认值的时候，但是直接删除的话，需要将所有的值开始重新截取

    this.props.onChange(e);
    this.setTooltip(e);
  };

  // 模糊查询，匹配Name或code
  filterTreeNode = (inputValue, treeNode) => {
    const { ralation, investmentType } = this.props;
    //此时更改以前组件的过滤问题
    //搜索的值是否是当前treeNode的父节点下，如果是则true
    parentGetByValue = [];
    parentGetByKeys = [];
    let keys = [];
    let paramArr;
    if (ralation) {
      keys = [];
      paramArr = this.state.groupDS;
    } else {
      keys = [];
      paramArr = !investmentType ? (this.props.productCode ? this.props.productAGroup2M.productGroupFuZhai : this.props.productAGroup2M.productGroup) : this.state.dataSource;
    }
    if (!Array.isArray(paramArr)) {
      return false;
    }
    let datass = this.getParentBySearchValue(paramArr, inputValue, true);
    let dataKeys = this.getParentByKeys(paramArr, treeNode.key, true);
    this.findParentKey(paramArr, keys);
    this.setState({
      treeExpandedKeys: keys,
    });
    if (datass.find((item) => item.key == dataKeys[0].key)) {
      return true;
    } else {
      return false;
    }
    // let portfolioCode = treeNode.props.portfolioCode;
    // let portfolioName = treeNode.props.portfolioName;
    // return portfolioCode.indexOf(inputValue) > -1 || portfolioName.indexOf(inputValue) > -1
  };
  //处理数据变成需要的内容
  handleData = (dataProduct) => {
    return this.showData(dataProduct);
  };
  circleGet = (datas, searchStores) => {
    for (var i = 0; i < datas.length; i++) {
      if (datas[i].key == searchStores) {
        valueData = datas[i].portfolioCode;
      } else {
        if (datas[i]?.children?.length) {
          this.circleGet(datas[i].children, searchStores);
        }
      }
    }
    return valueData;
  };
  onBlur = () => {
    const { value, multiple } = this.props;
    const { searchInputValue } = this.state;
    //单选模式的时候 失去焦点的时候 需要清空 searchInput
    if (!value && !multiple) {
      this.setState({
        searchInputValue: '',
      });
    }
    if ((!value && !searchInputValue && !multiple) || (multiple && !value?.length && !searchInputValue)) {
      this.setState({ displayType: 1 });
    } else if ((!multiple && value) || (multiple && value?.length && !searchInputValue)) {
      this.setState({ displayType: 2 });
    } else {
      this.setState({ displayType: 3 });
    }
  };
  showData = (dataProduct) => {
    let { searchInputValue, tooltipInfo, tooltips, displayType } = this.state;
    const { multiple, treeCheckable } = this.props;
    switch (displayType) {
      case 1:
        return this.sliceMaxArr(dataProduct);
        break;
      case 2:
        let datas_ = [];
        let datas = {};
        if (tooltips) {
          if (multiple) {
            //如果是多选的情况
            if (Array.isArray(tooltips) && tooltips.length) {
              for (var i = 0; i < tooltips.length; i++) {
                parentGetByKeys = [];
                datas = this.getParentByKeys(dataProduct, tooltips[i], true);
                datas_.push(...datas);
                datas_ = Array.from(new Set(datas_)); //以防选择的是两个同个父级
              }
              return this.sliceMaxArr(datas_);
            }
          } else {
            parentGetByKeys = [];
            const datas = this.getParentByKeys(dataProduct, tooltips && tooltips.length && tooltips[0], true);
            datas_.push(...datas);
            datas_ = Array.from(new Set(datas_));
            return this.sliceMaxArr(datas_);
          }
        }
        break;
      case 3:
        parentGetByValue = [];
        parentGetByKeys = [];
        let newArr = null;
        let addArr = null;
        let datass = this.getParentBySearchValue(dataProduct, searchInputValue, true);
        if (!multiple) {
          //多选的时候，需要加输入的值与已有的值合并在一起
          newArr = this.getParentByKeys(this.sliceMaxArr(datass), tooltips[0], true);
          if (newArr && newArr.length == 0) {
            parentGetByKeys = [];
            addArr = this.getParentByKeys(dataProduct, tooltips[0], true);
            this.sliceMaxArr(datass).push(...addArr);
            return Array.from(new Set(this.sliceMaxArr(datass)));
          } else {
            return this.sliceMaxArr(datass);
          }
        } else {
          return this.sliceMaxArr(datass);
        }
        break;
      default:
        break;
    }
  };
  //处理最大展示数的地方
  sliceMaxArr = (datas) => {
    const count = this.props.maxMountDataShow;
    if (datas.length && datas.length > count) {
      return datas.slice(0, count);
    } else {
      return datas;
    }
  };
  //通过key获取到那一层的数据
  getParentByKeys = (data, keys, flag) => {
    for (var j = 0; j < data.length; j++) {
      if (flag) parentNodeByKeys = {};
      if (data[j].key == keys) {
        if (flag) {
          parentGetByKeys.push(data[j]);
        } else {
          parentGetByKeys.push(parentNodeByKeys);
        }
      } else {
        if (data[j]?.children?.length) {
          if (flag) parentNodeByKeys = data[j];
          this.getParentByKeys(data[j].children, keys);
        }
      }
    }
    return parentGetByKeys;
  };
  getParentBySearchValue = (datas, value, flag) => {
    //参数分别对应 拿到的所有值的数据  拿到所有值数据的克隆值 搜索的输入值  目前的index值
    //如果有的话则拿它以及它以下的数据，如果没有的话则拿第一次的数据
    for (var i = 0; i < datas.length; i++) {
      if (flag) parentNode = {};
      if (datas[i].portfolioCode?.indexOf(value) > -1 || datas[i].portfolioName?.indexOf(value) > -1) {
        if (!flag) {
          parentGetByValue.push(parentNode);
          parentGetByValue = Array.from(new Set(parentGetByValue));
        } else {
          parentGetByValue.push(datas[i]);
          parentGetByValue = Array.from(new Set(parentGetByValue));
        }
      } else {
        if (datas[i]?.children?.length) {
          if (flag) parentNode = datas[i];
          this.getParentBySearchValue(datas[i].children, value);
        }
      }
    }
    return parentGetByValue;
  };
  //这边是处理模糊查询的地方
  handleSearch = (v) => {
    const { value, multiple } = this.props;
    //如果搜索的值有值 或者是 选择了值之后
    //1.搜索值有但是未选中，展示搜索值 2.搜索值有但是选中，展示搜索值
    //2.搜索值无但是未选中，展示所有 4.搜索值无，但是选中，展示选中值
    this.setState(
      {
        searchInputValue: v,
        // displayType:(v===''&&(value?.length)&&2) || 1
        displayType: v ? 3 : value?.length ? 2 : 1,
      },
      () => {
        let keys = [];
        if (this.props.ralation) {
          this.findParentKey(this.state.groupDS, keys);
        } else {
          if (this.props.investmentType) {
            this.findParentKey(this.state.dataSource, keys);
          } else {
            this.findParentKey(this.props.productCode ? this.props.productAGroup2M.productGroupFuZhai : this.props.productAGroup2M.productGroup, keys);
          }
        }

        this.setState({
          treeExpandedKeys: keys,
        });
      },
    );
  };
  render() {
    const { styleRow, value, initialValue, placeholder, maxTagCount, width, ralation, multiple, allowClear, disabled, treeCheckable, toolTipPlace, positionBody, investmentType } =
      this.props;
    const { dataSource } = this.state;
    return (
      <Tooltip title={this.state.tooltipInfo} placement={toolTipPlace == undefined ? (multiple == true ? 'right' : 'top') : toolTipPlace}>
        <div>
          <TreeSelect
            getPopupContainer={(triggerNode) => (!positionBody ? triggerNode.parentNode : document.body)}
            value={value}
            style={styleRow ? styleRow : { width: width }}
            maxTagCount={maxTagCount}
            placeholder={placeholder} // 占位符
            onChange={this.onChange} // 选中树节点时调用此函数
            treeData={
              // 数据源
              ralation
                ? this.state.groupDS != undefined && Array.isArray(this.state?.groupDS)
                  ? this.state.groupDS.length > moreMaxDataNeedModify
                    ? this.handleData(this.state.groupDS)
                    : this.state.groupDS
                  : [{ value: 'blank', title: '正在加载中...', disabled: true }]
                : !!investmentType
                ? Array.isArray(dataSource)
                  ? dataSource
                  : [{ value: 'blank', title: '正在加载中...', disabled: true }]
                : this.props.productCode
                ? this.props.productAGroup2M.productGroupFuZhai != undefined && Array.isArray(this.props.productAGroup2M?.productGroupFuZhai)
                  ? this.props.productAGroup2M.productGroupFuZhai.length > moreMaxDataNeedModify
                    ? this.handleData(this.props.productAGroup2M.productGroupFuZhai)
                    : this.props.productAGroup2M.productGroupFuZhai
                  : [{ value: 'blank', title: '正在加载中...', disabled: true }]
                : this.props.productAGroup2M.productGroup != undefined && Array.isArray(this.props.productAGroup2M?.productGroup)
                ? this.props.productAGroup2M.productGroup.length > moreMaxDataNeedModify
                  ? this.handleData(this.props.productAGroup2M.productGroup)
                  : this.props.productAGroup2M.productGroup
                : [{ value: 'blank', title: '正在加载中...', disabled: true }]
            }
            multiple={multiple} // 支持多选（当设置 treeCheckable 时自动变为 true）
            treeCheckable={treeCheckable} // 设置checkbox的显示或隐藏
            showCheckedStrategy={treeCheckable ? TreeSelect.SHOW_ALL : TreeSelect.SHOW_CHILD}
            allowClear={allowClear} // 显示清除按钮
            treeDefaultExpandAll={true} // 默认展开所有树节点（仅初始化时生效）
            treeExpandedKeys={ralation ? this.state.treeExpandedKeys : this.state.treeExpandedKeys} // 设置树节点展开
            onTreeExpand={ralation ? this.onTreeExpand : this.onTreeExpand} // 树节点展开调用事件
            dropdownMatchSelectWidth={true} // 下拉菜单和选择器同宽
            disabled={disabled}
            // autoClearSearchValue={false}
            onBlur={this.onBlur}
            showSearch={true} // 支持模糊查询
            filterTreeNode={true} //用组件自带的搜索 以title 进行模糊匹配
            // filterTreeNode={ this.filterTreeNode} //搜索函数 输入数字卡顿严重  去掉
            treeNodeFilterProp='title'
            defaultValue={initialValue}
            onSearch={this.handleSearch}
          />
        </div>
      </Tooltip>
    );
  }
}

// props类型
ProductGroupTreeC.propsTypes = {
  form: PropTypes.object, // form对象
  title: PropTypes.string, // 显示名称
  dataIndex: PropTypes.string, // Form识别的Item ID
  initialValue: PropTypes.oneOfType([
    // 初始默认值
    PropTypes.string, // 单选模式
    PropTypes.array, // 多选模式
  ]),
  rules: PropTypes.object, // 校验规则
  placeholder: PropTypes.string, // 占位符
  onChange: PropTypes.func, // 输入框内容变化时的回调
  helper: PropTypes.oneOfType([
    // 提示帮助信息
    PropTypes.string,
    PropTypes.element,
  ]),
  onRef: PropTypes.func, // 本组件的引用（可用来父组件调用内部方法）
  maxTagCount: PropTypes.number,
  productId: PropTypes.string, // 产品ID（在ralation为true时，设置productId生效）
  ralation: PropTypes.bool, // 设置是否与产品有关联关系
  multiple: PropTypes.bool, // 是否支持多选
  allowClear: PropTypes.bool, // 设置是否可删除
  authority: PropTypes.oneOf(['read', 'write']), // 设置权限类型
  disabled: PropTypes.bool, // 是否禁用
  treeCheckable: PropTypes.bool, // 是否显示checkbox
  maatApi: PropTypes.bool, // 正常情况下，在哪个环境下，就访问哪个环境的组合，
  // 但在投资建议书模块中，被引用到资管环境时，该组件的接口仍然要访问maat环境中的组合（而不是资管环境中组合），此时需要在接口前添加maat前缀
  toolTipPlace: PropTypes.string, // tooltip显示位置(未设置时，默认多选时展示在右边，单选时展示在上面，设置了就按设置的位置展示)
};

export default connect(({ productAGroup2M, loading }) => ({ productAGroup2M, loading }))(ProductGroupTreeC);
